

$.fn.betweenParent = function(selector){
    if(this.length !== 1)
        throw "element num must be 1";

    var result = [this[0]];
    var cur = this;
    while(!cur.is(selector)){
        cur = cur.parent();
        if(cur[0] === document.documentElement)
            throw "not found";
        result.push(cur[0]);
    }
    return $(result);
};

$(function(){

    // var maxEdgeWidth = [20, 20, 20, 20];
    var maxEdgeWidth;
    $(window).on("resize", _maxEdgeWidth);
    function _maxEdgeWidth(){
        maxEdgeWidth = Math.floor(window.innerWidth / 1366 * 20) || 1;
    }
    _maxEdgeWidth();

    var containers;
    var rows;
    var cols;

    var target = null;
    var direction;  // 1：上  2：右  3：下  4：左

    var eventLayer = 0;

    var cover = $("<div id='cover'/>").css({
        position: "absolute",
        zIndex: "999999999",
        border: "2px dashed black",
        "line-height": "25px",
        "text-align": "center",
        display: "none"
    }).appendTo(document.body);

    var end_callback;
    var insertElement;

    // function body_end(){ }
    // function body_mousemove(e){ }

    window.container_init = container_init;

    function container_init(callback, insert){
        end_callback = callback;
        insertElement = insert;

        // console.log("container init");
        containers = $(".container").$init().$saveState("out", {
            mouseenter: container_enter
        }).$saveState("in", {
            mousemove: container_move,
            mouseleave: contianer_leave,
            mouseup: common_up
        }).$changeState("out").$push();
        // eventLayer++;

        return containers;
            // .$on("mouseenter", container_enter)
            // .$on("mousemove", container_move)
    // .$on("mouseup", contianer_leave);
    }
    function container_enter(e){
        // console.log("container enter");
        // $e.statePush();
        row_init(this);
        $(this).add(rows).$push();
        eventLayer++;
        $(this).$changeState("in");
    }
    function container_move(e){
        // console.log("container move");
        var tar = setTarget([e.pageX, e.pageY], this);
        // setCover(tar.target, tar.direction);
        setCover(tar.target, tar.direction, $(tar.target)[0].className);
        // var distance = 9999999999;
        // if(rows){
        //     rows.each(function(){
        //         var position = isun.getPosition(this);
        //         var dist = position[1] - e.pageY;
        //         if(dist > 0 && dist < distance){
        //             distance = dist;
        //             target = this;
        //             direction = 1;
        //         }
        //         dist = e.pageY - position[1] - this.offsetHeight;
        //         if(dist > 0 && dist < distance){
        //             distance = dist;
        //             target = this;
        //             direction = 3;
        //         }
        //     });
        //     setCover(target, direction);
        // }
    }
    function contianer_leave(e){
        // console.log("container leave");
        $e.stateBack();
        cover.hide();
        //TODO 插入容器的判定呢？
        // target = null;
        // direction = undefined;
    }
    function common_up(e){

        // console.log("common_up");

        if($(target).is(".container")){
            switch(direction){
                case 1:
                    $(target).before(
                        $("<div class='container'></div>").append(
                            $("<div class='row'></div>").append(
                                $("<div class='col-xs-12'></div>").append(insertElement)
                            )
                        )
                    );
                    break;
                case 2:
                    $(target).append(
                        $("<div class='row'></div>").append(
                            $("<div class='col-xs-6'></div>").append(
                                $(target).children()
                            )
                        ).append(
                            $("<div class='col-xs-6'></div>").append(insertElement)
                        )
                    );
                    break;
                case 3:
                    $(target).after(
                        $("<div class='container'></div>").append(
                            $("<div class='row'></div>").append(
                                $("<div class='col-xs-12'></div>").append(insertElement)
                            )
                        )
                    );
                    break;
                case 4:
                    $(target).append(
                        $("<div class='row'></div>").append(
                            $("<div class='col-xs-6'></div>").append(insertElement)
                        ).append(
                            $("<div class='col-xs-6'></div>").append(
                                $(target).children()
                            )
                        )
                    );
                    break;
            }
        }else if($(target).is(".row")){
            switch(direction){
                case 1:
                    $(target).before(
                        $("<div class='row'></div>").append(
                            $("<div class='col-xs-12'></div>").append(insertElement)
                        )
                    );
                    break;
                case 2:
                    $(target).append(
                        $("<div class='col-xs-6'></div>").append(
                            $("<div class='row'></div>").append($(target).children())
                        )
                    ).append(
                        $("<div class='col-xs-6'></div>").append(insertElement)
                    );
                    break;
                case 3:
                    $(target).after(
                        $("<div class='row'></div>").append(
                            $("<div class='col-xs-12'></div>").append(insertElement)
                        )
                    );
                    break;
                case 4:
                    $(target).append(
                        $("<div class='col-xs-6'></div>").append(
                            $("<div class='row'></div>").append($(target).children())
                        )
                    ).prepend(
                        $("<div class='col-xs-6'></div>").append(insertElement)
                    );
                    break;
            }
            // switch(direction){
            //     case 1:
            //         $(target).before("<div class='row'><div class='col-xs-12'></div></div>");
            //         break;
            //     case 2:
            //
            //         break;
            //     case 3:
            //         $(target).after("<div class='row'><div class='col-xs-12'></div></div>");
            //         break;
            //     case 4:
            //
            //         break;
            // }
        }else if($(target).is("*[class|=col]")){
            switch(direction){
                case 1:
                    $(target).prepend(insertElement);
                    break;
                case 2:
                case 4:
                    if(!insertElement){
                        var entireWidth = 0;
                        var els = [];
                        $(target).siblings().add(target).each(function(i){
                            var className = this.className.match(/^col-\w\w-\d{1,2}$/g)[0];
                            if(className){
                                entireWidth += Number(className.substr(className.lastIndexOf("-") + 1));
                                els[i] = [className, this];
                            }
                        });

                        var operation = ({2: "after", 4: "before"})[direction];
                        if(entireWidth < 12)
                            $(target)[operation](
                                $("<div class='col-xs-" + (12 - entireWidth) + "'></div>")
                            );
                        else if(els.length < 12){
                            // var keys = Object.keys(els);
                            var width = parseInt(12 / (els.length + 1));
                            els.forEach(function(v){
                                var className = v[0].substr(0, v[0].lastIndexOf("-") + 1) + width;
                                $(v[1]).removeClass(v[0]).addClass(className);
                            });
                            $(target)[operation](
                                $("<div class='col-xs-" + (12 - width * els.length) + "'></div>")
                            );
                        }
                    }else{
                        operation = ({2: "append", 4: "prepend"})[direction];
                        $(target).append(
                            $("<div class='row'></div>").append(
                                $("<div class='col-xs-6'></div>").append($(target).children())
                            )[operation](
                                $("<div class='col-xs-6'></div>").append(insertElement)
                            )
                        );
                    }
                    break;
                case 3:
                case 5:
                    // console.log("--------------------------------");
                    $(target).append(insertElement);
                    break;
            }
        }else if($(target).is(".ctl")){
            switch(direction){
                case 1:
                    $(target).before(insertElement);
                    break;
                case 2:
                    var parent = $(target).parent();
                    $(target).parent().children(".ctl").each(function(){
                        parent.append(
                            $("<div class='row'></div>").append(
                                $("<div class='col-xs-12'></div>").append(this)
                            )
                        );
                    });
                    $(target).parent().after(
                        $("<div class='col-xs-6'></div>").append(insertElement)
                    ).removeClass("col-xs-12").addClass("col-xs-6");
                    break;
                case 3:
                    $(target).after(insertElement);
                    break;
                case 4:
                    var parent = $(target).parent();
                    $(target).parent().children(".ctl").each(function(){
                        parent.append(
                            $("<div class='row'></div>").append(
                                $("<div class='col-xs-12'></div>").append(this)
                            )
                        );
                    });
                    $(target).parent().before(
                        $("<div class='col-xs-6'></div>").append(insertElement)
                    ).removeClass("col-xs-12").addClass("col-xs-6");
                    break;
            }
        }
        cover.hide();
        // $e.stateBack(eventLayer);
        // console.log(insertElement);
        if(end_callback){
            // console.log("call back-----");
            end_callback();
        }
    }

    function row_init(container){
        // console.log("row init");
        container = $(container);
        rows = container.children(".row").$init().$saveState("out", {
            mouseenter: row_enter
        }).$saveState("in", {
            mousemove: row_move,
            mouseleave: row_leave,
            mouseup: common_up
        }).$changeState("out");

        return rows;
            // .$on("mouseenter", row_enter)
            // .$on("mousemove", row_move)
            // .$on("mouseleave", row_leave);
    }
    function row_enter(e){
        // console.log("row enter");
        var cols = col_init(this);
        // $e.statePush();
        $(this).add(cols).$push();
        eventLayer++;
        $(this).$changeState("in");
    }
    function row_move(e){
        // console.log("row move");
        var tar = setTarget([e.pageX, e.pageY], this);
        // setCover(tar.target, tar.direction);
        setCover(tar.target, tar.direction, $(tar.target)[0].className);

    }
    function row_leave(e){
        // console.log("row leave");
        $e.stateBack();
    }

    function col_init(row){
        row = $(row);
        cols = row.children("*[class|=col]").$init().$saveState("out",{
            mouseenter: col_enter
        }).$saveState("in", {
            mousemove: col_move,
            mouseleave: col_leave,
            mouseup: common_up
        }).$changeState("out");
        return cols;
    }
    function col_enter(e){
        // console.log("col enter");
        var rows = row_init(this);
        var ctls = ctl_init(this);
        $(this).add(rows).add(ctls).$push();
        $(this).$changeState("in");
        // eventLayer++;


    }
    function col_move(e){
        // console.log("col move");
        var tar = setTarget([e.pageX, e.pageY], this);
        setCover(tar.target, tar.direction, $(tar.target)[0].className);
    }
    function col_leave(e){
        // console.log("col leave");
        $e.stateBack();
    }

    function ctl_init(col){
        col =  $(col);
        return col.children(".ctl").$init().$saveState("out", {
            mouseenter: ctl_enter
        }).$saveState("in", {
            mousemove: ctl_move,
            mouseleave: ctl_leave,
            mouseup: common_up
        }).$changeState("out");
    }
    function ctl_enter(e){
        $(this).$push().$changeState("in");
    }
    function ctl_move(e){
        var tar = setTarget([e.pageX, e.pageY], this);
        setCover(tar.target, tar.direction, $(tar.target)[0].className);
    }
    function ctl_leave(e){
        $e.stateBack();
    }


    function setTarget(p, el){
        el = $(el);

        // console.log(el[0].className);

        var portion = isun.getPortionIndex(p, el[0]);
        var q = el.betweenParent(".container");
        // var gap;
        // switch(portion.index){
        //     case 1:
        //     case 3:
        //         el[0].offsetWidth
        //     case 2:
        //     case 4:
        //     default:
        // }

        var el_corner = isun.getPosition(el);
        el_corner.push(el_corner[0] + el[0].offsetWidth);
        el_corner.push(el_corner[1] + el[0].offsetHeight);
        // el_corner = [el_corner[0], el_corner[1], el_corner[0] + el[0].offsetWidth, el_corner[1] + el[0].offsetHeight];      //[x, y, x2, y2]

        var getGap;
        switch(portion.index){
            case 1:
                getGap = function(outer){
                    return el_corner[1] - isun.getPosition(outer)[1];
                }; break;
            case 2:
                getGap = function(outer){
                    return isun.getPosition(outer)[0] + outer.offsetWidth - el_corner[2];
                }; break;
            case 3:
                getGap = function(outer){
                    return isun.getPosition(outer)[1] + outer.offsetHeight - el_corner[3];
                }; break;
            case 4:
                getGap = function(outer){
                    return el_corner[0] - isun.getPosition(outer)[0];
                }; break;
            default:
                return;
        }

        var lastGap;
        for(var i = q.length - 1; i > 0; i--){
            lastGap = getGap(q[i]);
            if(lastGap >= maxEdgeWidth){
                q.length--;
            }else
                break;
        }

        var total,width;

        width = portion.index % 2 ? Math.floor(el[0].offsetHeight * 0.35 / q.length) : Math.floor(el[0].offsetWidth * 0.35 / q.length);   //q include current element
        if(width > maxEdgeWidth) width = maxEdgeWidth;

        if(lastGap === undefined || lastGap >= maxEdgeWidth || !width){
            total = 0;
            return self();
        }

        // if(!width) return self();

        var headWidth = Math.floor(width / maxEdgeWidth * (maxEdgeWidth - lastGap)) || 1;
        total = width * (q.length - 2) + headWidth;

        if(portion.dist > total) return self();
        // console.log(portion.dist, total, width);

        target = q[q.length - Math.floor((portion.dist + width - headWidth - 1) / width) - 1];
        direction = portion.index;
        return {
            target: target,
            direction: portion.index
        };

        function self(){
            var direc = portion.index;
            if(el.is("*[class|=col]") && insertElement && portion.dist > total + width){
                direc = 5;
            }
            target = el[0];
            direction = direc;
            return {
                target: el[0],
                direction: direc
            };
        }

        // el = $(el);
        // var p_i;
        // var q = el.betweenParent(".container");
        //
        //
        // // console.log("-- q --", q);
        //
        // if(q.length > 1){
        //     var pre_edgeWidth = maxEdgeWidth.clone();  //检测的边距大小 [top, right, bottom, left]
        //     var q_last = q[q.length - 1];
        //     var pre_space = isun.getPosition(q_last);  //前一个元素所在位置及大小 [x, y, x2, y2]
        //     pre_space = [pre_space[0], pre_space[1], pre_space[0] + q_last.offsetWidth, pre_space[1] + q_last.offsetHeight];
        //
        //     p_i = isun.getPortionIndex(p, q_last, pre_edgeWidth);
        //     if(p_i.index){
        //         // target = q_last;
        //         // direction = p_i;
        //         return {
        //             target: q_last,
        //             direction: p_i.index
        //         };
        //     }
        //
        //     for(var i = q.length - 2; i > 0; i--){
        //
        //         var cur_space = isun.getPosition(q[i]);
        //         cur_space = [cur_space[0], cur_space[1], q[i].offsetWidth + cur_space[0], q[i].offsetHeight + cur_space[1]];
        //         var borderGap = [cur_space[1] - pre_space[1], pre_space[2] - cur_space[2], pre_space[3] - cur_space[3], cur_space[0] - pre_space[0]];
        //         // var edge_p = [borderGap[0] - pre_edgeWidth[0], borderGap[1] - pre_edgeWidth[1], borderGap[2] - pre_edgeWidth[2], borderGap[3] - pre_edgeWidth[3]].map(function(v){return v > 0 ? v : 0;});
        //         var edge = borderGap.map(function(v, i){
        //             v = pre_edgeWidth[i] - v;
        //             if(v < 0) v = 0;
        //             return maxEdgeWidth[i] + v;
        //         });
        //         pre_edgeWidth = edge;
        //         pre_space = cur_space;
        //
        //         p_i = isun.getPortionIndex(p, q[i], edge);
        //         // p_i = isun.getPortionIndex(p, q[i], [15,15,15,15]);
        //         if(p_i.index){
        //             target = q[i];
        //             direction = p_i.index;
        //             return {
        //                 target: q[i],
        //                 direction: p_i.index
        //             };
        //         }
        //     }
        // }
        //
        // if($(q[0]).is("*[class|=col]") && insertElement){
        //     p_i = isun.getPortionIndex(p, q[0]);
        //     if(p_i.index){
        //         if(q.length > 1){
        //             cur_space = isun.getPosition(q[0]);
        //             cur_space = [cur_space[0], cur_space[1], q[i].offsetWidth + cur_space[0], q[i].offsetHeight + cur_space[1]];
        //             borderGap = [cur_space[1] - pre_space[1], pre_space[2] - cur_space[2], pre_space[3] - cur_space[3], cur_space[0] - pre_space[0]];
        //             edge = borderGap.map(function(v, i){
        //                 v = pre_edgeWidth[i] - v;
        //                 if(v < 0) v = 0;
        //                 return maxEdgeWidth[i] + v;
        //             });
        //             p_i = isun.getPortionIndex(p, q[0], edge);
        //         }else{
        //             p_i = isun.getPortionIndex(p, q[0], maxEdgeWidth.clone());
        //         }
        //         if(p_i.index === 0) p_i = 5;
        //     }
        // }else{
        //     p_i = isun.getPortionIndex(p, q[0]);
        // }
        // target = q[0];
        // direction = p_i.index;
        // return {
        //     target: q[0],
        //     direction: p_i.index
        // };

    }

    function setCover(el, direction, desc){
        el = $(el)[0];
        var position = isun.getPosition(el);
        cover.css({
            left: position[0] + "px",
            top: position[1] + "px",
            width: el.offsetWidth + "px",
            height: el.offsetHeight + "px",
            border: "2px dashed black"
        });
        if(direction === 5)
            cover.css("border", "3px solid black");
        else if(direction)
            cover.css("border-" + ["top", "right", "bottom", "left"][direction - 1], "3px solid black");

        desc = desc || "";
        cover.html(desc);
        cover.show();
    }

});


// function body_mouseup(e){
//
// }
// function container_mouseup(){
//
// }
// function row_mouseup(){
//
// }

